#ifndef CDATABASE_H
#define CDATABASE_H

#include <QString>
#include <QVariant>

#include <QtSql>
#include <QtXml>
#include <QtDebug>

struct CChange
{
    QString id;
    int type;
    int action;
    QString datetime;
};

typedef QMap<QString, QVariant> ChangeMap;

class CDatabase
{
    static void debug(QString msg) { qDebug() << "[CDatabase]\t" + msg; }

    QString m_filename;

    bool open(bool = false);

    enum
    {
        Entry,
        Section,
        Field
    };

    enum
    {
        Add,
        Edit,
        Delete
    };

    bool addChange(QString entry_id, int entry_type, int action_type);
    QString getTableByType(int);
    int getTypeByTable(QString);

    QStringList getSectionBlobs();
    QStringList getEntryBlobs();
    QStringList getFieldBlobs();

    QStringList getBlobsByType(int);

public:
    CDatabase(QString name = QString());
    ~CDatabase();

    bool add(QMap<QString, QVariant> map, QString table, bool encrypted = false);
    bool update(QMap<QString, QVariant> map, QString id, QString table, bool encrypted = false);

/* Cathrgory functions */
    QMap<QString, QVariant> getSection(QString id);
    QVariant getSectionAttr(QString id, QString name);

    QList<QString> getSectionChildern(QString id);
    int getSectionEntriesCount(QString id);

    QString getSectionParent(QString id) { return getSectionAttr(id, "parent").toString(); }
    QVariant getSectionIcon(QString id) { return getSectionAttr(id, "icon"); }

    bool addSection(QMap<QString, QVariant>);
    bool deleteSection(QString id);
    bool updateSection(QMap<QString, QVariant>, QString);
/* Section functions */

/* Entry functions */
    QList<QString> getEntriesList(QString id);
    QMap<QString, QVariant> getEntry(QString id);

    int getEntryFieldsCount(QString id);
    QList<QMap<QString, QVariant> > getEntryFields(QString id);

    bool addEntry(QMap<QString, QVariant>);
    bool deleteEntry(QString id);
    bool updateEntry(QMap<QString, QVariant>, QString);

    //bool addField(QString entry_id, QVariant name, int type, QVariant value, int order);
    bool addField(QMap<QString, QVariant>);
    //bool updateField(QString id, QVariant name, int type, QVariant value, int order);
    bool updateField(QMap<QString, QVariant>, QString);
    bool deleteField(QString id);
/* Entry functions */

    QList<CChange> changes();
    QList<ChangeMap*> changedEntries();
    QList<ChangeMap*> changedFields();
    QList<ChangeMap*> changedSections();
    QMap<QString, QString> properties(QStringList);

    void setLastSync();
    QString lastSync();

    bool setFilename(QString name) { m_filename = name; return open(true); }
    QString filename() { return m_filename; }

    void close();// { QSqlDatabase::database().close(); }
    bool isNew();
    bool isOpen() { return QSqlDatabase::database().isOpen(); }

    QString getKeyMd5();
    bool setKey(QString);

    bool importChanges(QByteArray&);
    bool insertValue(QDomNode&, QString);
    bool processType(QDomNode&, QString);
    bool exists(QString id, QString table);

    static bool createDatabase(QString filename, QString cipher, QString key);
    static QByteArray encrypt_array(QByteArray);
    static QByteArray decrypt_array(QByteArray);
    static QString genMd5(QString);
};

#endif // CDATABASE_H
